package org.pay.service.impl;

import org.apache.commons.collections.CollectionUtils;
import org.springframework.stereotype.Service;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.pay.core.common.Exception.ServiceException;
import org.pay.core.common.constant.MchConstant;
import org.pay.core.common.domain.BaseParam;
import org.pay.core.common.enumm.RetEnum;
import org.pay.core.common.util.JsonUtil;
import org.pay.core.common.util.MyLog;
import org.pay.core.common.util.ObjectValidUtil;
import org.pay.core.common.util.RpcUtil;
import org.pay.core.entity.*;
import org.pay.core.service.IMchChannelService;
import org.pay.service.dao.mapper.ChannelConfigMapper;
import org.pay.service.dao.mapper.MchChannelMapper;
import org.pay.service.BaseService;
import org.pay.service.dao.mapper.MchInfoMapper;

import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

/**
 * @author: yangshancheng
 * @date: 17/9/8
 * @description:
 */
@Service
public class MchChannelServiceImpl extends BaseService implements IMchChannelService {

    private static final MyLog _log = MyLog.getLog(MchChannelServiceImpl.class);

    @Autowired
    private MchChannelMapper mchChannelMapper;

    @Autowired
    private ChannelConfigMapper channelConfigMapper;

    @Autowired
    private MchInfoMapper mchInfoMapper;

    @Override
    public Map selectMchChannel(String jsonParam) {
        BaseParam baseParam = JsonUtil.getObjectFromJson(jsonParam, BaseParam.class);
        Map<String, Object> bizParamMap = baseParam.getBizParamMap();
        if (ObjectValidUtil.isInvalid(bizParamMap)) {
            _log.warn("查询支付渠道信息失败, {}. jsonParam={}", RetEnum.RET_PARAM_NOT_FOUND.getMessage(), jsonParam);
            return RpcUtil.createFailResult(baseParam, RetEnum.RET_PARAM_NOT_FOUND);
        }
        Long mchId = baseParam.isNullValue("mchId") ? null : Long.parseLong(bizParamMap.get("mchId").toString());
        String channelId = baseParam.isNullValue("channelId") ? null : bizParamMap.get("channelId").toString();
        if (ObjectValidUtil.isInvalid(mchId, channelId)) {
            _log.warn("查询支付渠道信息失败, {}. jsonParam={}", RetEnum.RET_PARAM_INVALID.getMessage(), jsonParam);
            return RpcUtil.createFailResult(baseParam, RetEnum.RET_PARAM_INVALID);
        }
        MchChannel mchChannel = super.baseSelectMchChannel(mchId, channelId);
        if(mchChannel == null) return RpcUtil.createFailResult(baseParam, RetEnum.RET_BIZ_DATA_NOT_EXISTS);
        String jsonResult = JsonUtil.object2Json(mchChannel);
        return RpcUtil.createBizResult(baseParam, jsonResult);
    }

    @Override
    public int add(MchChannel mchChannel) {
        return mchChannelMapper.insertSelective(mchChannel);
    }

    @Override
    public int update(MchChannel mchChannel) {
        return mchChannelMapper.updateByPrimaryKeySelective(mchChannel);
    }

    @Override
    public MchChannel findById(int id) {
        return mchChannelMapper.selectByPrimaryKey(id);
    }

    @Override
    public MchChannel findByMACId(Long mchId, String appId, String channelId) {
        MchChannelExample example = new MchChannelExample();
        MchChannelExample.Criteria criteria = example.createCriteria();
        criteria.andMchIdEqualTo(mchId);
        criteria.andAppIdEqualTo(appId);
        criteria.andChannelIdEqualTo(channelId);
        List<MchChannel> mchChannelList = mchChannelMapper.selectByExample(example);
        if(CollectionUtils.isEmpty(mchChannelList)) return null;
        return mchChannelList.get(0);
    }

    @Override
    public List<MchChannel> select(int offset, int limit, MchChannel mchChannel) {
        MchChannelExample example = new MchChannelExample();
        example.setOrderByClause("mch_id ASC, channel_id ASC, create_time DESC");
        example.setOffset(offset);
        example.setLimit(limit);
        MchChannelExample.Criteria criteria = example.createCriteria();
        setCriteria(criteria, mchChannel);
        return mchChannelMapper.selectByExample(example);
    }

    @Override
    public Integer count(MchChannel mchChannel) {
        MchChannelExample example = new MchChannelExample();
        MchChannelExample.Criteria criteria = example.createCriteria();
        setCriteria(criteria, mchChannel);
        return mchChannelMapper.countByExample(example);
    }

    @Override
    public List<MchChannel> selectByMch(Long mchId, String appId, Byte scene) {
        MchInfo mchInfo = mchInfoMapper.selectByPrimaryKey(mchId);
        if(mchInfo == null) {
            throw new ServiceException(org.pay.core.common.constant.RetEnum.RET_SERVICE_MCH_NOT_EXIST);
        }
        ChannelConfigExample example = new ChannelConfigExample();
        ChannelConfigExample.Criteria criteria = example.createCriteria();
        example.setOrderByClause("scene asc");
        criteria.andStatusEqualTo(MchConstant.PUB_YES);
        // 得到官方支持的渠道列表
        List<ChannelConfig> channelConfigList = channelConfigMapper.selectByExample(example);
        if(CollectionUtils.isEmpty(channelConfigList)) return new LinkedList<>();
        List<String> channelIdList = new LinkedList<>();
        for(ChannelConfig channelConfig : channelConfigList) {
            channelIdList.add(channelConfig.getChannelId());
        }

        MchChannelExample mchChannelExample = new MchChannelExample();
        MchChannelExample.Criteria mchChannelCriteria = mchChannelExample.createCriteria();
        if(mchId != null) mchChannelCriteria.andMchIdEqualTo(mchId);
        if(appId != null) mchChannelCriteria.andAppIdEqualTo(appId);
        if(scene != null) mchChannelCriteria.andSceneEqualTo(scene);
        mchChannelCriteria.andChannelIdIn(channelIdList);
        // 得到应用已配置的渠道
        List<MchChannel> mchChannelList = mchChannelMapper.selectByExample(mchChannelExample);

        Map<String, MchChannel> mchChannelMap = new HashMap<>();
        for(MchChannel mchChannel : mchChannelList) {
            mchChannelMap.put(mchChannel.getChannelId(), mchChannel);
        }

        // 遍历支持的渠道,如果应用配置了使用应用自身的渠道配置,否则使用官方的配置
        List<MchChannel> retMchChannelList = new LinkedList<>();
        for(ChannelConfig channelConfig : channelConfigList) {
            channelIdList.add(channelConfig.getChannelId());
            MchChannel mchChannel = mchChannelMap.get(channelConfig.getChannelId());
            if(mchChannel == null) {
                mchChannel = new MchChannel();
                mchChannel.setMchId(mchId);
                mchChannel.setName(mchInfo.getName());
                mchChannel.setAppId(appId);
                mchChannel.setChannelId(channelConfig.getChannelId());
                mchChannel.setChannelType(channelConfig.getChannelType());
                mchChannel.setScene(channelConfig.getScene());
                mchChannel.setState(MchConstant.PUB_NO); // 默认未开通
                mchChannel.setParam(channelConfig.getParam());
                mchChannel.setRemark(channelConfig.getRemark());
            }
            retMchChannelList.add(mchChannel);
        }

        return retMchChannelList;
    }

    @Override
    public List<MchChannel> selectByChannelIds(MchChannel mchChannel, List<String> channelIds) {
        MchChannelExample example = new MchChannelExample();
        MchChannelExample.Criteria criteria = example.createCriteria();
        setCriteria(criteria, mchChannel);
        criteria.andChannelIdIn(channelIds);
        return mchChannelMapper.selectByExample(example);
    }

    @Override
    public List<MchChannel> selectAll(MchChannel mchChannel) {
        MchChannelExample example = new MchChannelExample();
        example.setOrderByClause("channel_mch_id asc");
        MchChannelExample.Criteria criteria = example.createCriteria();
        setCriteria(criteria, mchChannel);
        return mchChannelMapper.selectByExample(example);
    }

    void setCriteria(MchChannelExample.Criteria criteria, MchChannel mchChannel) {
        if(mchChannel != null) {
            if(mchChannel.getMchId() != null) criteria.andMchIdEqualTo(mchChannel.getMchId());
            if(StringUtils.isNotBlank(mchChannel.getAppId())) criteria.andAppIdEqualTo(mchChannel.getAppId());
            if(StringUtils.isNotBlank(mchChannel.getChannelId())) criteria.andChannelIdEqualTo(mchChannel.getChannelId());
            if(mchChannel.getState() != null) criteria.andStatusEqualTo(mchChannel.getState());
        }
    }
}
